home *** CD-ROM | disk | FTP | other *** search
/ EuroCD 3 / EuroCD 3.iso / Games / Doom / ADoom-0.8 / ADoom_src / w_wad.c < prev    next >
C/C++ Source or Header  |  1998-06-24  |  11KB  |  597 lines

  1. // Emacs style mode select   -*- C++ -*- 
  2. //-----------------------------------------------------------------------------
  3. //
  4. // $Id:$
  5. //
  6. // Copyright (C) 1993-1996 by id Software, Inc.
  7. //
  8. // This source is available for distribution and/or modification
  9. // only under the terms of the DOOM Source Code License as
  10. // published by id Software. All rights reserved.
  11. //
  12. // The source is distributed in the hope that it will be useful,
  13. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. // FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
  15. // for more details.
  16. //
  17. // $Log:$
  18. //
  19. // DESCRIPTION:
  20. //    Handles WAD file header, directory, lump I/O.
  21. //
  22. //-----------------------------------------------------------------------------
  23.  
  24.  
  25. static const char
  26. rcsid[] = "$Id: w_wad.c,v 1.5 1997/02/03 16:47:57 b1 Exp $";
  27.  
  28.  
  29. #ifdef NORMALUNIX
  30. #ifndef __SASC
  31. #include <ctype.h>
  32. #include <sys/types.h>
  33. #include <string.h>
  34. #include <unistd.h>
  35. #include <malloc.h>
  36. #include <fcntl.h>
  37. #include <sys/stat.h>
  38. #include <alloca.h>
  39. #define O_BINARY        0
  40. #else
  41. #include <stdio.h>
  42. #include <stdlib.h>
  43. #include <string.h>
  44. #include <ctype.h>
  45. #include <stat.h>
  46. #endif
  47. #endif
  48.  
  49. #include "doomdef.h"
  50. #include "doomtype.h"
  51. #include "m_swap.h"
  52. #include "i_system.h"
  53. #include "z_zone.h"
  54.  
  55. #ifdef __GNUG__
  56. #pragma implementation "w_wad.h"
  57. #endif
  58. #include "w_wad.h"
  59.  
  60.  
  61.  
  62.  
  63.  
  64.  
  65. //
  66. // GLOBALS
  67. //
  68.  
  69. // Location of each lump on disk.
  70. lumpinfo_t*        lumpinfo;        
  71. int            numlumps;
  72.  
  73. void**            lumpcache;
  74.  
  75.  
  76. #ifndef __SASC
  77. #define strcmpi    strcasecmp
  78.  
  79. void strupr (char* s)
  80. {
  81.     while (*s) { *s = toupper(*s); s++; }
  82. }
  83. #endif
  84.  
  85. int filelength (int handle) 
  86.     struct stat    *fileinfo;
  87.     int size;
  88.     
  89.     if ((fileinfo = malloc (sizeof(struct stat))) == NULL ||
  90.         fstat (handle,fileinfo) == -1)
  91.     I_Error ("Error fstating");
  92.     size = fileinfo->st_size;
  93.     free (fileinfo);
  94.  
  95.     return size;
  96. }
  97.  
  98.  
  99. void
  100. ExtractFileBase
  101. ( char*        path,
  102.   char*        dest )
  103. {
  104.     char*    src;
  105.     int        length;
  106.  
  107.     src = path + strlen(path) - 1;
  108.     
  109.     // back up until a \ or the start
  110.     while (src != path
  111.        && *(src-1) != '\\'
  112.        && *(src-1) != '/')
  113.     {
  114.     src--;
  115.     }
  116.     
  117.     // copy up to eight characters
  118.     memset (dest,0,8);
  119.     length = 0;
  120.     
  121.     while (*src && *src != '.')
  122.     {
  123.     if (++length == 9)
  124.         I_Error ("Filename base of %s >8 chars",path);
  125.  
  126.     *dest++ = toupper((int)*src++);
  127.     }
  128. }
  129.  
  130.  
  131.  
  132.  
  133.  
  134. //
  135. // LUMP BASED ROUTINES.
  136. //
  137.  
  138. //
  139. // W_AddFile
  140. // All files are optional, but at least one file must be
  141. //  found (PWAD, if all required lumps are present).
  142. // Files with a .wad extension are wadlink files
  143. //  with multiple lumps.
  144. // Other files are single lumps with the base filename
  145. //  for the lump name.
  146. //
  147. // If filename starts with a tilde, the file is handled
  148. //  specially to allow map reloads.
  149. // But: the reload feature is a fragile hack...
  150.  
  151. int            reloadlump;
  152. char*            reloadname;
  153.  
  154.  
  155. void W_AddFile (char *filename)
  156. {
  157.     wadinfo_t        header;
  158.     lumpinfo_t*        lump_p;
  159.     unsigned        i;
  160.     FILE        *handle;
  161.     int            length;
  162.     int            startlump;
  163.     filelump_t*        fileinfo = NULL;
  164.     filelump_t        singleinfo;
  165.     FILE        *storehandle;
  166.     
  167.     // open the file and add to directory
  168.  
  169.     // handle reload indicator.
  170.     if (filename[0] == '~')
  171.     {
  172.     filename++;
  173.     reloadname = filename;
  174.     reloadlump = numlumps;
  175.     }
  176.         
  177.     if ( (handle = fopen (filename,"r")) == NULL)
  178.     {
  179.     printf (" couldn't open %s\n",filename);
  180.     return;
  181.     }
  182.  
  183.     printf (" adding %s\n",filename);
  184.     startlump = numlumps;
  185.     
  186.     if (strcmpi (filename+strlen(filename)-3 , "wad" ) )
  187.     {
  188.     // single lump file
  189.     fileinfo = &singleinfo;
  190.     singleinfo.filepos = 0;
  191.     singleinfo.size = LONG(filelength(fileno(handle)));
  192.     ExtractFileBase (filename, singleinfo.name);
  193.     numlumps++;
  194.     }
  195.     else 
  196.     {
  197.     // WAD file
  198.     fread (&header, 1, sizeof(header), handle);
  199.     if (strncmp(header.identification,"IWAD",4))
  200.     {
  201.         // Homebrew levels?
  202.         if (strncmp(header.identification,"PWAD",4))
  203.         {
  204.         I_Error ("Wad file %s doesn't have IWAD "
  205.              "or PWAD id\n", filename);
  206.         }
  207.         
  208.         // ???modifiedgame = true;        
  209.     }
  210.     header.numlumps = LONG(header.numlumps);
  211.     header.infotableofs = LONG(header.infotableofs);
  212.     length = header.numlumps*sizeof(filelump_t);
  213.     fileinfo = malloc (length);
  214.     fseek (handle, header.infotableofs, SEEK_SET);
  215.     fread (fileinfo, 1, length, handle);
  216.     numlumps += header.numlumps;
  217.     }
  218.  
  219.     
  220.     // Fill in lumpinfo
  221.     lumpinfo = realloc (lumpinfo, numlumps*sizeof(lumpinfo_t));
  222.  
  223.     if (!lumpinfo)
  224.     I_Error ("Couldn't realloc lumpinfo");
  225.  
  226.     lump_p = &lumpinfo[startlump];
  227.     
  228.     storehandle = reloadname ? NULL : handle;
  229.     
  230.     for (i=startlump ; i<numlumps ; i++,lump_p++, fileinfo++)
  231.     {
  232.     lump_p->handle = storehandle;
  233.     lump_p->position = LONG(fileinfo->filepos);
  234.     lump_p->size = LONG(fileinfo->size);
  235.     strncpy (lump_p->name, fileinfo->name, 8);
  236.     }
  237.     
  238.     if (reloadname)
  239.     fclose (handle);
  240.     if (fileinfo != NULL)
  241.         free (fileinfo);
  242. }
  243.  
  244.  
  245.  
  246.  
  247. //
  248. // W_Reload
  249. // Flushes any of the reloadable lumps in memory
  250. //  and reloads the directory.
  251. //
  252. void W_Reload (void)
  253. {
  254.     wadinfo_t        header;
  255.     int            lumpcount;
  256.     lumpinfo_t*        lump_p;
  257.     unsigned        i;
  258.     FILE        *handle;
  259.     int            length;
  260.     filelump_t*        fileinfo = NULL;
  261.     
  262.     if (!reloadname)
  263.     return;
  264.         
  265.     if ( (handle = fopen (reloadname,"r")) == NULL)
  266.     I_Error ("W_Reload: couldn't open %s",reloadname);
  267.  
  268.     fread (&header, 1, sizeof(header), handle);
  269.     lumpcount = LONG(header.numlumps);
  270.     header.infotableofs = LONG(header.infotableofs);
  271.     length = lumpcount*sizeof(filelump_t);
  272.     fileinfo = malloc (length);
  273.     fseek (handle, header.infotableofs, SEEK_SET);
  274.     fread (fileinfo, 1, length, handle);
  275.     
  276.     // Fill in lumpinfo
  277.     lump_p = &lumpinfo[reloadlump];
  278.     
  279.     for (i=reloadlump ;
  280.      i<reloadlump+lumpcount ;
  281.      i++,lump_p++, fileinfo++)
  282.     {
  283.     if (lumpcache[i])
  284.         Z_Free (lumpcache[i]);
  285.  
  286.     lump_p->position = LONG(fileinfo->filepos);
  287.     lump_p->size = LONG(fileinfo->size);
  288.     }
  289.     
  290.     fclose (handle);
  291.     if (fileinfo != NULL)
  292.        free (fileinfo);
  293. }
  294.  
  295.  
  296.  
  297. //
  298. // W_InitMultipleFiles
  299. // Pass a null terminated list of files to use.
  300. // All files are optional, but at least one file
  301. //  must be found.
  302. // Files with a .wad extension are idlink files
  303. //  with multiple lumps.
  304. // Other files are single lumps with the base filename
  305. //  for the lump name.
  306. // Lump names can appear multiple times.
  307. // The name searcher looks backwards, so a later file
  308. //  does override all earlier ones.
  309. //
  310. void W_InitMultipleFiles (char** filenames)
  311. {    
  312.     int        size;
  313.     
  314.     // open all the files, load headers, and count lumps
  315.     numlumps = 0;
  316.  
  317.     // will be realloced as lumps are added
  318.     lumpinfo = malloc(1);    
  319.  
  320.     for ( ; *filenames ; filenames++)
  321.     W_AddFile (*filenames);
  322.  
  323.     if (!numlumps)
  324.     I_Error ("W_InitFiles: no files found");
  325.     
  326.     // set up caching
  327.     size = numlumps * sizeof(*lumpcache);
  328.     lumpcache = malloc (size);
  329.     
  330.     if (!lumpcache)
  331.     I_Error ("Couldn't allocate lumpcache");
  332.  
  333.     memset (lumpcache,0, size);
  334. }
  335.  
  336.  
  337.  
  338.  
  339. //
  340. // W_InitFile
  341. // Just initialize from a single file.
  342. //
  343. void W_InitFile (char* filename)
  344. {
  345.     char*    names[2];
  346.  
  347.     names[0] = filename;
  348.     names[1] = NULL;
  349.     W_InitMultipleFiles (names);
  350. }
  351.  
  352.  
  353.  
  354. //
  355. // W_NumLumps
  356. //
  357. int W_NumLumps (void)
  358. {
  359.     return numlumps;
  360. }
  361.  
  362.  
  363.  
  364. //
  365. // W_CheckNumForName
  366. // Returns -1 if name not found.
  367. //
  368.  
  369. int W_CheckNumForName (char* name)
  370. {
  371.     union {
  372.     char    s[9];
  373.     int    x[2];
  374.     
  375.     } name8;
  376.     
  377.     int        v1;
  378.     int        v2;
  379.     lumpinfo_t*    lump_p;
  380.  
  381.     // make the name into two integers for easy compares
  382.     strncpy (name8.s,name,8);
  383.  
  384.     // in case the name was a fill 8 chars
  385.     name8.s[8] = 0;
  386.  
  387.     // case insensitive
  388.     strupr (name8.s);        
  389.  
  390.     v1 = name8.x[0];
  391.     v2 = name8.x[1];
  392.  
  393.  
  394.     // scan backwards so patch lump files take precedence
  395.     lump_p = lumpinfo + numlumps;
  396.  
  397.     while (lump_p-- != lumpinfo)
  398.     {
  399.     if ( *(int *)lump_p->name == v1
  400.          && *(int *)&lump_p->name[4] == v2)
  401.     {
  402.         return lump_p - lumpinfo;
  403.     }
  404.     }
  405.  
  406.     // TFB. Not found.
  407.     return -1;
  408. }
  409.  
  410.  
  411.  
  412.  
  413. //
  414. // W_GetNumForName
  415. // Calls W_CheckNumForName, but bombs out if not found.
  416. //
  417. int W_GetNumForName (char* name)
  418. {
  419.     int    i;
  420.  
  421.     i = W_CheckNumForName (name);
  422.     
  423.     if (i == -1)
  424.       I_Error ("W_GetNumForName: %s not found!", name);
  425.       
  426.     return i;
  427. }
  428.  
  429.  
  430. //
  431. // W_LumpLength
  432. // Returns the buffer size needed to load the given lump.
  433. //
  434. int W_LumpLength (int lump)
  435. {
  436.     if (lump >= numlumps)
  437.     I_Error ("W_LumpLength: %i >= numlumps",lump);
  438.  
  439.     return lumpinfo[lump].size;
  440. }
  441.  
  442.  
  443.  
  444. //
  445. // W_ReadLump
  446. // Loads the lump into the given buffer,
  447. //  which must be >= W_LumpLength().
  448. //
  449. void
  450. W_ReadLump
  451. ( int        lump,
  452.   void*        dest )
  453. {
  454.     int        c;
  455.     lumpinfo_t*    l;
  456.     FILE    *handle;
  457.     
  458.     if (lump >= numlumps)
  459.     I_Error ("W_ReadLump: %i >= numlumps",lump);
  460.  
  461.     l = lumpinfo+lump;
  462.     
  463.     // ??? I_BeginRead ();
  464.     
  465.     if (l->handle == NULL)
  466.     {
  467.     // reloadable file, so use open / read / close
  468.     if ( (handle = fopen (reloadname,"r")) == NULL)
  469.         I_Error ("W_ReadLump: couldn't open %s",reloadname);
  470.     }
  471.     else
  472.     handle = l->handle;
  473.         
  474.     fseek (handle, l->position, SEEK_SET);
  475.     c = fread (dest, 1, l->size, handle);
  476.  
  477.     if (c < l->size)
  478.     I_Error ("W_ReadLump: only read %i of %i on lump %i",
  479.          c,l->size,lump);    
  480.  
  481.     if (l->handle == NULL)
  482.     fclose (handle);
  483.         
  484.     // ??? I_EndRead ();
  485. }
  486.  
  487.  
  488.  
  489.  
  490. //
  491. // W_CacheLumpNum
  492. //
  493. void*
  494. W_CacheLumpNum
  495. ( int        lump,
  496.   int        tag )
  497. {
  498.     byte*    ptr;
  499.  
  500.     if ((unsigned)lump >= numlumps)
  501.     I_Error ("W_CacheLumpNum: %i >= numlumps",lump);
  502.         
  503.     if (!lumpcache[lump])
  504.     {
  505.     // read the lump in
  506.     
  507.     //printf ("cache miss on lump %i\n",lump);
  508.     ptr = Z_Malloc (W_LumpLength (lump), tag, &lumpcache[lump]);
  509.     W_ReadLump (lump, lumpcache[lump]);
  510.     }
  511.     else
  512.     {
  513.     //printf ("cache hit on lump %i\n",lump);
  514.     Z_ChangeTag (lumpcache[lump],tag);
  515.     }
  516.     
  517.     return lumpcache[lump];
  518. }
  519.  
  520.  
  521.  
  522. //
  523. // W_CacheLumpName
  524. //
  525. void*
  526. W_CacheLumpName
  527. ( char*        name,
  528.   int        tag )
  529. {
  530.     return W_CacheLumpNum (W_GetNumForName(name), tag);
  531. }
  532.  
  533.  
  534. //
  535. // W_Profile
  536. //
  537. FAR int        info[2500][10];
  538. int        profilecount;
  539.  
  540. void W_Profile (void)
  541. {
  542.     int        i;
  543.     memblock_t*    block;
  544.     void*    ptr;
  545.     char    ch;
  546.     FILE*    f;
  547.     int        j;
  548.     char    name[9];
  549.     
  550.     
  551.     for (i=0 ; i<numlumps ; i++)
  552.     {    
  553.     ptr = lumpcache[i];
  554.     if (!ptr)
  555.     {
  556.         ch = ' ';
  557.         continue;
  558.     }
  559.     else
  560.     {
  561.         block = (memblock_t *) ( (byte *)ptr - sizeof(memblock_t));
  562.         if (block->tag < PU_PURGELEVEL)
  563.         ch = 'S';
  564.         else
  565.         ch = 'P';
  566.     }
  567.     info[i][profilecount] = ch;
  568.     }
  569.     profilecount++;
  570.     
  571.     f = fopen ("waddump.txt","w");
  572.     name[8] = 0;
  573.  
  574.     for (i=0 ; i<numlumps ; i++)
  575.     {
  576.     memcpy (name,lumpinfo[i].name,8);
  577.  
  578.     for (j=0 ; j<8 ; j++)
  579.         if (!name[j])
  580.         break;
  581.  
  582.     for ( ; j<8 ; j++)
  583.         name[j] = ' ';
  584.  
  585.     fprintf (f,"%s ",name);
  586.  
  587.     for (j=0 ; j<profilecount ; j++)
  588.         fprintf (f,"    %c",info[i][j]);
  589.  
  590.     fprintf (f,"\n");
  591.     }
  592.     fclose (f);
  593. }
  594.  
  595.  
  596.